package me.zhengjie.modules.weixin.processor.impl;


import me.zhengjie.modules.weixin.dto.WeChatAccount;
import me.zhengjie.modules.weixin.enums.WeChatMsgTypeEnum;
import me.zhengjie.modules.weixin.message.AnalyzerReplyMessage;
import me.zhengjie.modules.weixin.message.receive.ReceiveTextMessage;
import me.zhengjie.modules.weixin.message.reply.AbstractReplyMessage;
import me.zhengjie.modules.weixin.message.reply.ReplyNewsMessage;
import me.zhengjie.modules.weixin.processor.AbstractProcessor;
import me.zhengjie.modules.weixin.utils.ClazzUtil;
import me.zhengjie.modules.weixin.utils.WeChatUtil;
import me.zhengjie.utils.http.HttpUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UserapiProcessor extends AbstractProcessor {

    public UserapiProcessor() {

    }

    public UserapiProcessor(WeChatAccount account, AnalyzerReplyMessage reply) {
        this.account = account;
        this.reply = reply;
    }

    @Override
    public AbstractReplyMessage process() throws Exception {

        Map<String, Object> receiveMsg = reply.getReceiveMsg();
        String openId = (String) receiveMsg.get("FromUserName");
        String original = (String) receiveMsg.get("ToUserName");

        String rid = reply.getRule();

        AbstractReplyMessage result = null;

        return result;
    }

    private AbstractReplyMessage procRemote(String apiUrl, String token) throws Exception {

        Map<String, Object> receiveMsg = reply.getReceiveMsg();
        String from = (String) receiveMsg.get("FromUserName");
        String to = (String) receiveMsg.get("ToUserName");
        String content = (String) receiveMsg.get("Content");

        String copyApiUrl = apiUrl + (StringUtils.contains(apiUrl, "?") ? "&" : "?");

        String timestamp = WeChatUtil.INSTANCE.createTimestamp();
        String nonce = WeChatUtil.INSTANCE.createNonceStr();

        String signature = WeChatUtil.INSTANCE.buildSignature(token, timestamp, nonce);

        copyApiUrl += "signature=" + signature + "&timestamp=" + timestamp + "&nonce=" + nonce;

        ReceiveTextMessage textMsg = WeChatUtil.INSTANCE.convertMap2Bean(reply.getReceiveMsg(), ReceiveTextMessage.class);
        if (null == textMsg) {
            textMsg = new ReceiveTextMessage();
            textMsg.setFromUserName(from);
            textMsg.setToUserName(to);
            textMsg.setContent(content);
            textMsg.setCreateTime(System.currentTimeMillis() / 1000);
            textMsg.setMsgType(WeChatMsgTypeEnum.text.name());
            textMsg.setMsgId((Long) receiveMsg.get("MsgId"));
        }
        String httpStr = HttpUtils.post(copyApiUrl, textMsg.toXML(), "text/xml; charset=utf-8");
        if (StringUtils.isBlank(httpStr)) {
            return null;
        }

        // 如果需要在远程地址中处理上下文锁定,需要在远程地址返回的数据中附加特定标记.
        if (StringUtils.contains(httpStr, "{begin-context}")) {
            beginContext(0);
            httpStr = httpStr.replace("{begin-context}", "");
        }
        if (StringUtils.contains(httpStr, "{end-context}")) {
            endContext();
            httpStr = httpStr.replace("{end-context}", "");
        }

        AbstractReplyMessage result = null;

        Map<String, Object> httpObj = WeChatUtil.INSTANCE.convertXml2Map(httpStr);

        String msgType = (String) httpObj.get("MsgType");
        WeChatMsgTypeEnum msgTypeEnum = WeChatMsgTypeEnum.get(msgType);
        switch (msgTypeEnum) {
            case text:
                result = respText((String) httpObj.get("Content"));
                break;
            case image:
                result = respImage((String) httpObj.get("MediaId"));
                break;
            case voice:
                result = respVoice((String) httpObj.get("MediaId"));
                break;
            case video:
                Map<String, Object> video = new HashMap<>();
                video.put("title", "");
                video.put("mediaid", httpObj.get("MediaId"));
                video.put("description", httpObj.get("ThumbMediaId"));
                result = respVideo(video);
                break;
            case music:
                Map<String, Object> music = new HashMap<>();
                music.put("title", httpObj.get("Title"));
                music.put("url", httpObj.get("MusicUrl"));
                music.put("description", httpObj.get("Description"));
                music.put("hqurl", httpObj.get("HQMusicUrl"));
                music.put("thumbMediaId", httpObj.get("ThumbMediaId"));
                result = respMusic(music);
                break;
            case news:
                ReplyNewsMessage newMsg = (ReplyNewsMessage) WeChatUtil.INSTANCE.getXStream().fromXML(httpStr, ReplyNewsMessage.class);
                List<Map<String, Object>> news = new ArrayList<>();
                for (ReplyNewsMessage.NewsMessage newItem : newMsg.getArticles()) {
                    Map<String, Object> item = new HashMap<>(8);
                    item.put("title", httpObj.get("Title"));
                    item.put("url", httpObj.get("Url"));
                    item.put("description", httpObj.get("Description"));
                    item.put("thumb", httpObj.get("PicUrl"));
                    news.add(item);
                }
                result = respNews(news);
            case location:
            case link:
            case event:
            case other:
            case shortvideo:
            case transfer_customer_service:
            default:
                break;
        }

        return result;
    }


    private AbstractReplyMessage procLocal(String apiUrl) throws Exception {
        String copyApiUrl = apiUrl.replace(".php", "");

        Class<?> clazz = ClazzUtil.INSTANCE.getReflectClass(copyApiUrl);
        if (null == clazz) {
            return null;
        }
        Constructor constructor = clazz.getConstructor(WeChatAccount.class, AnalyzerReplyMessage.class);
        UserapiProcessor processor = (UserapiProcessor) constructor.newInstance(account, reply);

        return processor.execute();
    }

    public AbstractReplyMessage execute() {
        return null;
    }
}
